package com.telrob.bytevm.compile;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.telrob.bytevm.natives.Natives;
import com.telrob.bytevm.utils.ToolUtils;

public class Compile {
	public static void main(String[] args) {
		compile("main.xn");
	}
	public static void compile(String file) {
		ByteArrayOutputStream bout=new ByteArrayOutputStream();
		
		List<Instruct> instructList=ToolUtils.register();
		FileOutputStream fout=null;
		//标签的索引位置,如 abc:这种伪指令
		Map<String,Integer>labelIndex=new HashMap<String, Integer>();
		//需要替换的位置
		List<ReplaceCode>labelReplace=new ArrayList<ReplaceCode>();
		try {
			byte[]nameTable=Natives.getMethodTable();
			bout.write(nameTable);
			file=file.substring(0,file.length()-3);
			String bin=file+".bin";
			fout=new FileOutputStream(bin);
			List<String> list=parse(file+".xn");
			//System.err.println("开始解析");
			for(String instruct:list) {
				//System.err.println(instruct);
				String[]lines=instruct.split("[ ,\t]");
				boolean is=false;
				for(Instruct ins:instructList) {
					String opt=lines[0];
					int size=bout.size();
					//当是伪指令时候，需要记录下位置
					if(ins.isPseudo(opt)) {
						is=true;
						String key=opt.replace(":", "");
						labelIndex.put(key, size);
						continue;
					}
					if(ins.isComplie(opt)) {
						is=true;
						byte[]bb=ins.complie(instruct,lines,size,labelReplace);
						if(bb==null) {
							System.err.println("无法解析的指令"+instruct);
						}
						bout.write(bb);
						break;
					}
				}
				if(is==false) {
					System.err.println("不能解析 "+instruct);
					System.exit(0);
				}
			}
			byte[]data=bout.toByteArray();
			
			//对标号进行替换
			if(labelReplace!=null&&labelReplace.size()>0) {
				for(ReplaceCode code:labelReplace) {
					String name=code.getName();
					int index=code.getIndex();
					//System.err.println("##"+name);
					int val=labelIndex.get(name);
					//System.err.println("-------------");
					//System.err.println(name);
					//System.err.println("详细地址:"+val);
					//System.err.println(index);
					byte[]dd=ToolUtils.int2bytes(val);
					data[index+0]=dd[0];
					data[index+1]=dd[1];
					data[index+2]=dd[2];
					data[index+3]=dd[3];
				}
			}
			// str="";
			//for(int i=0;i<data.length;i++) {
			//	str+=String.format("0X%02X", data[i])+",";
			//}
			//System.err.println(str);
			
			
			fout.write(data);
			fout.flush();
			System.err.println("编译完成 "+bin);
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			try {
				bout.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if(fout!=null) {
					fout.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/***
	 * 读取文件行 去除掉换行和
	 * @param fileName 文件名
	 * @return
	 */
	public static List<String> parse(String fileName){
		List<String>result=new ArrayList<String>();
		BufferedReader br=null;
		try {
			br=new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
			String line=null;
			
			while(true) {
				line=br.readLine();
				if(line==null) {
					break;
				}
				//去除前面的空格和tab
				line=line.replaceAll("^[ ,\t]*", "");
				//去掉注释
				line=line.replaceAll("(;[\\W\\w]*)$", "");
				//空行
				if(line.equals("")) {
					continue;
				}
				result.add(line);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(br!=null) {
				try {
					br.close();
				} catch (IOException e) {
				}
			}
		}
		return result;
	}
}
